﻿#pragma once

#include <learn/geom/nurbs.h>

namespace xi
{

namespace geom
{

template <std::size_t N> class Geom_Surface
{
    static_assert(N > 1, "N must be greater than 1");
    using Vec = VecT<N, double>;

  public:
    /**
     * @brief 参数范围
     *
     * @return std::array<double, 4>
     */
    virtual std::array<double, 4> bounds() const = 0;

    /**
     * @brief 计算曲面上点的位置
     *
     * @param[in] u
     * @param[in] v
     * @return Vec
     */
    virtual Vec d0(double u, double v) const = 0;

    /**
     * @brief 计算曲面上点的位置和导数
     *
     * @param[in] u
     * @param[in] v
     * @return std::array<Vec, 3>
     */
    virtual std::array<Vec, 3> d1(double u, double v) const = 0;

    /**
     * @brief 计算曲面上点的位置和二阶导数
     *
     * @param[in] u
     * @param[in] v
     * @return std::array<Vec, 6>
     */
    virtual std::array<Vec, 6> d2(double u, double v) const = 0;

    /**
     * @brief 将曲面信息序列化为 json 格式
     *
     * @return utils::Json
     */
    virtual utils::Json dump_json() const = 0;

    /**
     * @brief 计算曲面上点的位置
     *
     * @param[in] u
     * @param[in] v
     * @return Vec
     */
    Vec value(double u, double v) const
    {
        return d0(u, v);
    }
};

} // namespace geom

} // namespace xi
